/**
 * 统一通知工具函数
 * 只使用详细通知，支持自适应大小
 * 包含安全过滤和文本长度限制
 */

import { notification } from 'antd';
import type { ArgsProps as NotificationArgsProps } from 'antd/es/notification';

// 通知类型
export type NotificationType = 'success' | 'error' | 'info' | 'warning';

// 文本长度限制配置
const TEXT_LIMITS = {
  TITLE_MAX_LENGTH: 50,      // 标题最大长度
  DESCRIPTION_MAX_LENGTH: 200, // 描述最大长度
  ELLIPSIS: '...'            // 省略号
} as const;

/**
 * 安全过滤文本内容，防止XSS攻击
 * @param text 原始文本
 * @returns 过滤后的安全文本
 */
const sanitizeText = (text: string): string => {
  if (!text || typeof text !== 'string') {
    return '';
  }

  return text
    // 移除HTML标签
    .replace(/<[^>]*>/g, '')
    // 转义特殊字符
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;')
    .replace(/\//g, '&#x2F;')
    // 移除潜在的脚本内容
    .replace(/javascript:/gi, '')
    .replace(/on\w+\s*=/gi, '')
    // 移除控制字符（保留换行和制表符）
    .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '')
    // 移除多余的空白字符
    .replace(/\s+/g, ' ')
    .trim();
};

/**
 * 截断文本并添加省略号
 * @param text 原始文本
 * @param maxLength 最大长度
 * @returns 截断后的文本
 */
const truncateText = (text: string, maxLength: number): string => {
  if (!text || text.length <= maxLength) {
    return text;
  }

  return text.substring(0, maxLength - TEXT_LIMITS.ELLIPSIS.length) + TEXT_LIMITS.ELLIPSIS;
};

/**
 * 处理和验证通知文本
 * @param title 标题
 * @param description 描述
 * @returns 处理后的安全文本
 */
const processNotificationText = (title: string, description?: string) => {
  // 安全过滤
  const safeTitle = sanitizeText(title);
  const safeDescription = description ? sanitizeText(description) : undefined;

  // 长度限制和截断
  const processedTitle = truncateText(safeTitle, TEXT_LIMITS.TITLE_MAX_LENGTH);
  const processedDescription = safeDescription
    ? truncateText(safeDescription, TEXT_LIMITS.DESCRIPTION_MAX_LENGTH)
    : undefined;

  // 验证处理后的文本
  if (!processedTitle.trim()) {
    throw new Error('通知标题不能为空或只包含无效字符');
  }

  return {
    title: processedTitle,
    description: processedDescription
  };
};

/**
 * 显示通知（统一接口）
 * @param type 通知类型
 * @param title 通知标题
 * @param description 通知描述（可选，短文本时可省略）
 * @param duration 显示时长（秒），0表示不自动关闭
 * @param onClose 关闭回调
 */
export const showNotification = (
  type: NotificationType,
  title: string,
  description?: string,
  duration: number = 4.5,
  onClose?: () => void
) => {
  try {
    // 处理和验证文本内容
    const { title: safeTitle, description: safeDescription } = processNotificationText(title, description);

    const config: NotificationArgsProps = {
      message: safeTitle,
      description: safeDescription,
      duration,
      placement: 'topRight',
      onClose,
      className: safeDescription ? 'notification-with-description' : 'notification-compact',
    };

    return notification[type](config);
  } catch (error) {
    // 如果文本处理失败，显示错误通知
    console.error('通知文本处理失败:', error);

    const fallbackConfig: NotificationArgsProps = {
      message: '通知内容无效',
      description: '通知内容包含无效字符或过长，已被过滤',
      duration: 3,
      placement: 'topRight',
      className: 'notification-with-description',
    };

    return notification.warning(fallbackConfig);
  }
};

// 便捷方法 - 统一使用详细通知
export const notifySuccess = (title: string, description?: string, duration?: number) =>
  showNotification('success', title, description, duration);

export const notifyError = (title: string, description?: string, duration?: number) =>
  showNotification('error', title, description, duration);

export const notifyInfo = (title: string, description?: string, duration?: number) =>
  showNotification('info', title, description, duration);

export const notifyWarning = (title: string, description?: string, duration?: number) =>
  showNotification('warning', title, description, duration);

// 兼容原消息通知接口 - 转换为详细通知
export const messageSuccess = (content: string, duration?: number) =>
  showNotification('success', content, undefined, duration);

export const messageError = (content: string, duration?: number) =>
  showNotification('error', content, undefined, duration);

export const messageInfo = (content: string, duration?: number) =>
  showNotification('info', content, undefined, duration);

export const messageWarning = (content: string, duration?: number) =>
  showNotification('warning', content, undefined, duration);

/**
 * 销毁所有通知
 */
export const destroyAllNotifications = () => {
  notification.destroy();
};

/**
 * 销毁所有通知（兼容接口）
 */
export const destroyAll = () => {
  destroyAllNotifications();
};

// 兼容接口
export const destroyAllMessages = destroyAllNotifications;

/**
 * 获取文本长度限制配置（用于前端验证）
 */
export const getTextLimits = () => TEXT_LIMITS;

/**
 * 验证文本长度是否符合要求
 * @param title 标题
 * @param description 描述
 * @returns 验证结果
 */
export const validateTextLength = (title: string, description?: string) => {
  const titleLength = title ? title.length : 0;
  const descriptionLength = description ? description.length : 0;

  return {
    titleValid: titleLength > 0 && titleLength <= TEXT_LIMITS.TITLE_MAX_LENGTH,
    descriptionValid: !description || descriptionLength <= TEXT_LIMITS.DESCRIPTION_MAX_LENGTH,
    titleLength,
    descriptionLength,
    titleMaxLength: TEXT_LIMITS.TITLE_MAX_LENGTH,
    descriptionMaxLength: TEXT_LIMITS.DESCRIPTION_MAX_LENGTH
  };
};

/**
 * 安全显示通知（带额外验证）
 * @param type 通知类型
 * @param title 标题
 * @param description 描述
 * @param options 额外选项
 */
export const safeShowNotification = (
  type: NotificationType,
  title: string,
  description?: string,
  options: {
    duration?: number;
    onClose?: () => void;
    skipValidation?: boolean;
  } = {}
) => {
  const { duration = 4.5, onClose, skipValidation = false } = options;

  if (!skipValidation) {
    const validation = validateTextLength(title, description);

    if (!validation.titleValid) {
      console.warn(`通知标题长度无效: ${validation.titleLength}/${validation.titleMaxLength}`);
    }

    if (!validation.descriptionValid) {
      console.warn(`通知描述长度无效: ${validation.descriptionLength}/${validation.descriptionMaxLength}`);
    }
  }

  return showNotification(type, title, description, duration, onClose);
};
